package com.zhongfl.crm.service.impl.boss;

import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import com.zhongfl.crm.enums.boss.*;
import com.zhongfl.crm.exception.CRMException;
import com.zhongfl.crm.lixiao.mapper.ApproverUserMapper;
import com.zhongfl.crm.lixiao.mapper.OrderConfirmMapper;
import com.zhongfl.crm.lixiao.mapper.WorkOrderSettleConfirmMapper;
import com.zhongfl.crm.lixiao.mapper.WorkOrderSettleMapper;
import com.zhongfl.crm.model.boss.*;
import com.zhongfl.crm.service.boss.*;
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import tech.heptagram.channel.api.common.AssertUtils;

import javax.annotation.Resource;
import java.math.BigDecimal;
import java.util.*;
import java.util.stream.Collectors;


/**
 * @author wang.yuchuan
 * @date 2018/5/7
 */
@Service
public class WorkOrderSettleServiceImpl implements WorkOrderSettleService {

    @Resource
    private WorkOrderSettleMapper workOrderSettleMapper;

    @Resource
    private WorkOrderSettleConfirmMapper workOrderSettleConfirmMapper;

    @Resource
    private AmibaStaffService amibaStaffService;

    @Resource
    private WorkOrderService workOrderService;

    @Resource
    private SequenceService sequenceService;

    @Resource
    private CommonLogService commonLogService;

    @Resource
    private MessageSendTaskService messageSendTaskService;

    @Resource
    private OrderService orderService;

    @Resource
    private OrderConfirmMapper orderConfirmMapper;

    @Resource
    private ApproverUserMapper approverUserMapper;

    /**
     * 更新订单的贷款期限,批贷金额,贷款利率,是否一次性通过
     * @param workOrder
     * @param workOrderSettle
     */
    private void updateOrder(WorkOrder workOrder, WorkOrderSettle workOrderSettle){
        //如果工单是在审批库,需要录入订单批贷金额
        if(workOrder.getWorkOrderTypeCode().equals(WorkOrderTypeCode.LOAN_APPROVE)){
            if(Objects.isNull(workOrderSettle.getApprovalAmount()) || workOrderSettle.getApprovalAmount().compareTo(BigDecimal.ZERO)== 0){
                throw new CRMException("批贷金额不能为空或为0");
            }
            if(Objects.isNull(workOrderSettle.getLoanDuration()) ||  workOrderSettle.getLoanDuration() == 0 ){
                throw new CRMException("批贷期限不能为空或为0");
            }
            if(Objects.isNull(workOrderSettle.getRate()) || workOrderSettle.getRate().compareTo(BigDecimal.ZERO)== 0){
                throw new CRMException("贷款利率不能为空或为0!");
            }
            if(Objects.isNull(workOrderSettle.getPassByOneTime())){
                throw new CRMException("是否一次性批贷不能为空");
            }
            if (workOrderSettle.getPassByOneTime() == 0 && StringUtils.isEmpty(workOrderSettle.getApproveReason())) {
                throw new CRMException("非一次性批贷原因不能为空");
            }
            Order order = new Order();
            //发起一个审批
            generatConfirm(workOrderSettle,workOrder);
            //是否一次性通过
            //如果是巴长发起的结算则是否一次性通过信息直接存入订单表
            if(workOrder.getClaimStaffCode().equals(workOrder.getAssigneeStaffCode())){
                order.setPassByOneTime(workOrderSettle.getPassByOneTime());
            }
            if(workOrderSettle.getPassByOneTime() == 1 ){
                order.setApproveReason(ReasonType.OTHER);
            }else{
                order.setApproveReason(ReasonType.getEnumByName(workOrderSettle.getApproveReason()));
            }
            //贷款利率
            order.setRate(workOrderSettle.getRate());
            //批贷期限
            order.setLoanDuration(workOrderSettle.getLoanDuration());
            order.setOrderNo( workOrder.getOrderNo());
            //贷款金额
            order.setLoanAmount(workOrderSettle.getApprovalAmount());
            //批贷金额
            order.setApprovalAmount(workOrderSettle.getApprovalAmount());
            order.setCurrentStaffName(workOrder.getClaimStaffName());
            order.setCurrentStaffCode(workOrder.getClaimStaffCode());
            order.setCreatedBy(workOrderSettle.getCreatedBy());
            orderService.update(order);
        }
        //如果工单是在放款库,需要录入房本入库时间
        if (workOrder.getWorkOrderTypeCode().equals(WorkOrderTypeCode.LOANED)) {
            if(Objects.isNull(workOrderSettle.getHouseEntryTime())){
                throw new CRMException("房本入库时间不能为空");
            }
            if(Objects.isNull(workOrderSettle.getOneTimeLoaned())){
                throw new CRMException("是否一次性放款不能为空");
            }
            if (workOrderSettle.getOneTimeLoaned() == 0 && Objects.isNull(workOrderSettle.getLoanedReason())) {
                throw new CRMException("非一次性放款原因不能为空");
            }
            Order order = new Order();
            //发起一个审批
            generatConfirm(workOrderSettle,workOrder);
            //是否一次性通过
            //如果是巴长发起的结算则是否一次性通过信息直接存入订单表
            if(workOrder.getClaimStaffCode().equals(workOrder.getAssigneeStaffCode())){
                order.setOneTimeLoaned(workOrderSettle.getOneTimeLoaned());
            }
            //贷款金额
            order.setLoanAmount(workOrderSettle.getApprovalAmount());
            if(workOrderSettle.getOneTimeLoaned() == 1){
                order.setLoanedReason(ReasonType.OTHER);
            }else{
                order.setLoanedReason(ReasonType.getEnumByName(workOrderSettle.getLoanedReason()));
            }
            order.setHouseEntryTime(workOrderSettle.getHouseEntryTime());
            order.setOrderNo(workOrder.getOrderNo());
            order.setCurrentStaffName(workOrder.getClaimStaffName());
            order.setCurrentStaffCode(workOrder.getClaimStaffCode());
            order.setCreatedBy(workOrderSettle.getCreatedBy());
            orderService.update(order);
        }
    }

    /**
     * 生成一个一次性通过的审批任务
     * @param workOrderSettle
     * @param workOrder
     */
    private void  generatConfirm(WorkOrderSettle workOrderSettle,WorkOrder workOrder){
        OrderConfirmType orderConfirmType = null;
        Integer oneTime = 0;
        if(WorkOrderTypeCode.LOAN_APPROVE.equals(workOrder.getWorkOrderTypeCode())) {
            orderConfirmType = OrderConfirmType.PASS_BY_ONE_TIME;
            oneTime = workOrderSettle.getPassByOneTime();
        }
        if(WorkOrderTypeCode.LOANED.equals(workOrder.getWorkOrderTypeCode())) {
            orderConfirmType = OrderConfirmType.ONE_TIME_LOANED;
            oneTime = workOrderSettle.getOneTimeLoaned();
        }
        List<OrderConfirm> orderConfirms = orderConfirmMapper.selectByOrderNoAndType(workOrder.getOrderNo(), orderConfirmType.name());
        if(!orderConfirms.isEmpty()){
            for (OrderConfirm orderConfirm : orderConfirms) {
                if (orderConfirm.getDeleted() != 1){
                    orderConfirmMapper.deleteByOrderNo(orderConfirm);
                }
            }
        }
        //生成一个审批任务（一次性通过的审批任务)
        OrderConfirm confirm = new OrderConfirm();
        //生成一个审批编号
        String approvalNo = sequenceService.generateApprovalNo();
        confirm.setApprovalNo(approvalNo);
        confirm.setConfirmType(orderConfirmType);
        confirm.setCreatedBy(workOrderSettle.getModifiedBy());
        confirm.setModifiedBy(workOrderSettle.getModifiedBy());
        confirm.setOrderNo(workOrder.getOrderNo());
        confirm.setApplicantStaffName(workOrder.getClaimStaffName());
        confirm.setApplicantStaffCode(workOrder.getClaimStaffCode());
        if(workOrder.getClaimStaffCode().equals(workOrder.getAssigneeStaffCode())){
            confirm.setStatus(OrderConfirmStatus.CONFIRMED);
            confirm.setConfirmTime(new Date());
            confirm.setApproverStaffCode(workOrder.getAssigneeStaffCode());
            confirm.setApproverStaffName(workOrder.getAssigneeStaffName());
        }else{
            confirm.setStatus(OrderConfirmStatus.UN_CONFIRM);
        }
        confirm.setPassByOneTime(oneTime);
        if(WorkOrderTypeCode.LOAN_APPROVE.equals(workOrder.getWorkOrderTypeCode())) {
            confirm.setReasonType(ReasonType.getEnumByName(workOrderSettle.getApproveReason()));
        }
        if(WorkOrderTypeCode.LOANED.equals(workOrder.getWorkOrderTypeCode())) {
            confirm.setReasonType(ReasonType.getEnumByName(workOrderSettle.getLoanedReason()));
            confirm.setHouseEntryTime(workOrderSettle.getHouseEntryTime());
        }



        //生成审批人
        Integer receiveAmibaId = workOrder.getReceiveAmibaId();
        //根据amibaId查询审批人列表
        List<AmibaStaff> amibaStaffs = amibaStaffService.findByAmibaId(receiveAmibaId);
        List<AmibaStaff> manages = amibaStaffs.stream().filter(e -> e.getRole() == 10).collect(Collectors.toList());
        List<ApproverUser> approverUsers = new ArrayList<>();
        for (AmibaStaff manage : manages) {
            ApproverUser approverUser = new ApproverUser();
            approverUser.setApprovalNo(approvalNo);
            approverUser.setApproverStaffCode(manage.getStaffCode());
            approverUser.setApproverStaffName(manage.getStaffName());
            approverUsers.add(approverUser);
            approverUserMapper.insert(approverUser);
        }
        List<String> approverStaffCodes = approverUsers.stream().map(ApproverUser::getApproverStaffCode).collect(Collectors.toList());
        String staffCodes = StringUtils.join(approverStaffCodes, ",");
        confirm.setApproverStaffCodeList(staffCodes);
        orderConfirmMapper.insert(confirm);
        if(workOrder.getClaimStaffCode().equals(workOrder.getAssigneeStaffCode())){
            return;
        }
        Order order = orderService.findByOrderNo(workOrder.getOrderNo());
        // 保存消息体,发消息,把是否一次性通过传递过去,给巴长，让巴长审批
        OrderApproveMessage message = new OrderApproveMessage();
        message.setOrderNo(workOrder.getOrderNo());
        message.setApplicatStaffCode(workOrder.getClaimStaffCode());
        message.setId(confirm.getId());
        message.setPassByOneTime(confirm.getPassByOneTime());
        message.setApplicatStaffName(workOrder.getClaimStaffName());
        message.setApproverUsers(approverUsers);
        message.setName(order.getName());
        message.setOrderConfirmType(orderConfirmType);
        message.setHouseEntryTime(workOrderSettle.getHouseEntryTime());
        if(WorkOrderTypeCode.LOAN_APPROVE.equals(workOrder.getWorkOrderTypeCode())) {
            message.setReasonType(ReasonType.getEnumByName(workOrderSettle.getApproveReason()));
        }
        if(WorkOrderTypeCode.LOANED.equals(workOrder.getWorkOrderTypeCode())) {
            message.setReasonType(ReasonType.getEnumByName(workOrderSettle.getLoanedReason()));
        }
        messageSendTaskService.save(MessageSendType.ORDER_APPROVE_MSG, workOrder.getOrderNo(), UUID.randomUUID().toString(), TopicConsts.ORDER_APPROVE_PASS_BY_ONE_TIME, message);
    }


    @Override
    @Transactional(rollbackFor = Exception.class)
    public void save(WorkOrderSettle workOrderSettle, boolean redo) {
        AssertUtils.notNull(workOrderSettle, "工单结算单不能为Null");
//        AssertUtils.hasText(workOrderSettle.getOrderNo(), "结算单所属订单号不能为空");
        AssertUtils.hasText(workOrderSettle.getWorkOrderNo(), "结算单所属工单号不能为空");
        AssertUtils.hasText(workOrderSettle.getCreatedBy(), "结算单创建人不能为空");

        WorkOrder workOrder = workOrderService.findByWorkOrderNo(workOrderSettle.getWorkOrderNo());
        AssertUtils.notNull(workOrder, "工单不存在");

        if(!redo){
            //更新订单的贷款期限,批贷金额,贷款利率,是否一次性通过
            updateOrder(workOrder, workOrderSettle);
            WorkOrderSettle currentSettle = workOrderSettleMapper.selectByWorkOrderNo(workOrder.getWorkOrderNo());
            if(Objects.nonNull(currentSettle)){
                throw new CRMException("请不要重复提交");
            }
        }

        // 更改工单状态为已完成
        RxWorkOrderCompleted completedInfo = new RxWorkOrderCompleted();
        completedInfo.setWorkOrderNo(workOrder.getWorkOrderNo());
        completedInfo.setOper(workOrderSettle.getSubmitStaffName());
        completedInfo.setCompleteStaffCode(workOrderSettle.getSubmitStaffCode());
        completedInfo.setAutoGenerateNextWorkOrder(!redo);
        workOrderService.complete(completedInfo);


        // 如果工单是返库工单，且订单状态在申报库，原逻辑不会更新订单状态，因为redo=true，自动生成下个工单为false，故在此更新订单状态[申报库->审批库]
        Order order = orderService.findByOrderNo(workOrder.getOrderNo());
        if(redo && order.getStatus().equals(OrderStatus.STATUS_DECLARE)){
            Order updateOrder = new Order();
            updateOrder.setOrderNo(order.getOrderNo());
            updateOrder.setStatus(OrderStatus.STATUS_APPROVAL);
            updateOrder.setCreatedBy(workOrderSettle.getCreatedBy());
            updateOrder.setOperStaffCode(workOrderSettle.getSubmitStaffCode());
            orderService.updateStatus(updateOrder);
        }

        workOrderSettle.setOrderNo(workOrder.getOrderNo());
        workOrderSettle.setFromAmibaId(workOrder.getCreateAmibaId());
        workOrderSettle.setFromAmibaName(workOrder.getCreateAmibaName());
        workOrderSettle.setToAmibaId(workOrder.getReceiveAmibaId());
        workOrderSettle.setToAmibaName(workOrder.getReceiveAmibaName());
        //如果外部结算和内部结算都为0,生成的结算单已结算
        int flag = workOrderSettle.getOutsiteIncomeReceivedAmount()
                        .add(workOrderSettle.getOutsiteIncomeChargeAmount())
                        .add(workOrderSettle.getInsiteIncomeAmount()).compareTo(BigDecimal.ZERO);
        if(flag == 0){
            // 更改工单状态为已结算
            WorkOrder worko = new WorkOrder();
            worko.setWorkOrderNo(workOrder.getWorkOrderNo());
            worko.setStatus(WorkOrderStatus.SETTLED);
            workOrderService.update(worko);
            //更改结算状态
            workOrderSettle.setStatus(WorkOrderSettleStatus.SETTLED);
        }else{
            workOrderSettle.setStatus(WorkOrderSettleStatus.UN_SETTLE);
        }

        String settleNo = sequenceService.generateSettleNo();
        workOrderSettle.setSettleNo(settleNo);

        // 保存结算单
        workOrderSettleMapper.insertSelective(workOrderSettle);

        WorkOrderSettleStaffs staffs = findSettleStaffsByWorkOrderNo(workOrder.getWorkOrderNo());

        // 付款方巴员
        WorkOrderSettleConfirm fromStaff = buildSettleConfirm(settleNo,
            staffs.getPayMember().getStaffCode(),
            staffs.getPayMember().getStaffName(),
            AmibaStaffRole.MEMBER,
            WorkOrderSettleConfirmSettleType.PAYER,
            workOrderSettle.getCreatedBy(),flag );
        workOrderSettleConfirmMapper.insertSelective(fromStaff);

        // 付款方巴长
        WorkOrderSettleConfirm fromStaffManager = buildSettleConfirm(settleNo,
            staffs.getPayManager().getStaffCode(),
            staffs.getPayManager().getStaffName(),
            AmibaStaffRole.MANAGER,
            WorkOrderSettleConfirmSettleType.PAYER,
            workOrderSettle.getCreatedBy(),flag);
        workOrderSettleConfirmMapper.insertSelective(fromStaffManager);

        // 收款方巴长
        WorkOrderSettleConfirm toStaffManager = buildSettleConfirm(settleNo,
            staffs.getReceiveManager().getStaffCode(),
            staffs.getReceiveManager().getStaffName(),
            AmibaStaffRole.MANAGER,
            WorkOrderSettleConfirmSettleType.RECEIPTER,
            workOrderSettle.getCreatedBy(),flag);
        workOrderSettleConfirmMapper.insertSelective(toStaffManager);

        // 收款方巴员
        WorkOrderSettleConfirm toStaff = buildSettleConfirm(settleNo,
            staffs.getReceiveMember().getStaffCode(),
            staffs.getReceiveMember().getStaffName(),
            AmibaStaffRole.MEMBER,
            WorkOrderSettleConfirmSettleType.RECEIPTER,
            workOrderSettle.getCreatedBy(),flag);
        workOrderSettleConfirmMapper.insertSelective(toStaff);

        //新增消息通知任务（目前消息类型为微信模板消息，发送方式微信发送）
        //List<WorkOrderSettleConfirm> list = new ArrayList<>(4);
        //list.add(fromStaff);list.add(fromStaffManager);
        //list.add(toStaff);list.add(toStaffManager);
        ////过滤掉结算发起人
        //list = list.stream().filter(item -> !item.getStaffCode().equals(workOrderSettle.getSubmitStaffCode())).collect(Collectors.toList());
        ////待确认方去重
        //Set<String> staffCodeSet = new HashSet<>();
        //list = list.stream().filter(item -> staffCodeSet.add(item.getStaffCode())).collect(Collectors.toList());
        //for (WorkOrderSettleConfirm confirm : list) {
        //    MessageSendTask task = new MessageSendTask();
        //    task.setContent(confirm.getStaffCode());
        //    task.setMsgType(MessageSendType.WORK_ORDER_UNSETTLED_MSG);
        //    task.setSendMethod(MessageSendMethod.WECHAT_TEMPLATE_MSG);
        //    task.setRelationNo(workOrder.getWorkOrderNo());
        //    task.setCreatedBy(workOrderSettle.getCreatedBy());
        //    //一期不发结算通知
        //    //messageSendTaskMapper.insert(task);
        //}
        //if (workOrder.getWorkOrderTypeCode() == WorkOrderTypeCode.INFORMATION
        //        || workOrder.getWorkOrderTypeCode() == WorkOrderTypeCode.LOANED
        //        || workOrder.getWorkOrderTypeCode() == WorkOrderTypeCode.ROLLS) {
        //    if (toStaff.getStaffCode().equals(toStaffManager.getStaffCode()) && !workOrderSettle.getSubmitStaffCode().equals(toStaff.getStaffCode())) {
        //        MessageSendTask evaluateTask = new MessageSendTask();
        //        evaluateTask.setContent(toStaff.getStaffCode());
        //        evaluateTask.setMsgType(MessageSendType.WORK_ORDER_UNEVALUATE_MSG);
        //        evaluateTask.setSendMethod(MessageSendMethod.WECHAT_TEMPLATE_MSG);
        //        evaluateTask.setRelationNo(workOrder.getWorkOrderNo());
        //        evaluateTask.setCreatedBy(workOrderSettle.getCreatedBy());
        //        messageSendTaskMapper.insert(evaluateTask);
        //    } else {
        //        if (!workOrderSettle.getSubmitStaffCode().equals(toStaff.getStaffCode())) {
        //            MessageSendTask evaluateTask = new MessageSendTask();
        //            evaluateTask.setContent(toStaff.getStaffCode());
        //            evaluateTask.setMsgType(MessageSendType.WORK_ORDER_UNEVALUATE_MSG);
        //            evaluateTask.setSendMethod(MessageSendMethod.WECHAT_TEMPLATE_MSG);
        //            evaluateTask.setRelationNo(workOrder.getWorkOrderNo());
        //            evaluateTask.setCreatedBy(workOrderSettle.getCreatedBy());
        //            messageSendTaskMapper.insert(evaluateTask);
        //        }
        //        if (!workOrderSettle.getSubmitStaffCode().equals(toStaffManager.getStaffCode())) {
        //            MessageSendTask evaluateTask2 = new MessageSendTask();
        //            evaluateTask2.setContent(toStaffManager.getStaffCode());
        //            evaluateTask2.setMsgType(MessageSendType.WORK_ORDER_UNEVALUATE_MSG);
        //            evaluateTask2.setSendMethod(MessageSendMethod.WECHAT_TEMPLATE_MSG);
        //            evaluateTask2.setRelationNo(workOrder.getWorkOrderNo());
        //            evaluateTask2.setCreatedBy(workOrderSettle.getCreatedBy());
        //            messageSendTaskMapper.insert(evaluateTask2);
        //        }
        //    }
        //}


        // 发起人发起的同时, 即算是确认了。
        confirm(workOrderSettle.getSettleNo(),workOrderSettle.getRemark(), workOrderSettle.getSubmitStaffCode(), workOrderSettle.getSubmitStaffName());

        try {
            StringBuilder sb = new StringBuilder();
            sb.append("发起结算, 外部收入[实收]:").append(workOrderSettle.getOutsiteIncomeReceivedAmount());
            sb.append(" 外部收入[挂账]:").append(workOrderSettle.getOutsiteIncomeChargeAmount());
            sb.append(" 内部收入:").append(workOrderSettle.getInsiteIncomeAmount());
//            sb.append(" 外部支出:").append(workOrderSettle.getTotalOutcomeAmount());
            commonLogService.add(CommonLogType.WORK_ORDER,
                    CommonLogType.WORK_ORDER_SETTLE_GENERATE,
                    workOrderSettle.getWorkOrderNo(),
                    sb.toString(),
                    workOrderSettle.getCreatedBy());
        } catch (Exception e) {
            throw new CRMException("创建初始化日志失败", e);
        }
    }


    @Override
    @Transactional(rollbackFor = Exception.class)
    public void update(WorkOrderSettle workOrderSettle) {
        AssertUtils.hasText(workOrderSettle.getWorkOrderNo(), "结算单所属工单号不能为空");
        AssertUtils.hasText(workOrderSettle.getCreatedBy(), "结算单修改不能为空");
        WorkOrder workOrder = workOrderService.findByWorkOrderNo(workOrderSettle.getWorkOrderNo());
        AssertUtils.notNull(workOrder, "工单不存在");
        WorkOrderSettle currentSettle = workOrderSettleMapper.selectByWorkOrderNo(workOrder.getWorkOrderNo());

        //更新订单的贷款期限,批贷金额,贷款利率,是否一次性通过
        updateOrder(workOrder,workOrderSettle);
        boolean amountChanged = false;
        // 只要外部收入(实收或挂账) 内部收入有不同, 则重新发起结算
        if(workOrderSettle.getOutsiteIncomeReceivedAmount().compareTo(currentSettle.getOutsiteIncomeReceivedAmount()) != 0
            ||workOrderSettle.getOutsiteIncomeChargeAmount().compareTo(currentSettle.getOutsiteIncomeChargeAmount()) != 0
            || workOrderSettle.getInsiteIncomeAmount().compareTo(currentSettle.getInsiteIncomeAmount()) != 0){
            amountChanged = true;
        }

        // 双方结算金额没有改变, 需要要重新确认, 删除之前的结算单, 然后新生成一个结算单吧。
        if(amountChanged) {
            // 删除当前的结算单
            workOrderSettleMapper.deleteBySettleNo(currentSettle.getSettleNo());
            // 再重新创建一个新的结算单
            save(workOrderSettle, true);
        }else{
            WorkOrderSettle updateInfo = new WorkOrderSettle();
            updateInfo.setSettleNo(currentSettle.getSettleNo());
            updateInfo.setOutsiteIncomeReceivedAmount(workOrderSettle.getOutsiteIncomeReceivedAmount());
            updateInfo.setOutsiteIncomeChargeAmount(workOrderSettle.getOutsiteIncomeChargeAmount());
            updateInfo.setInsiteIncomeAmount(workOrderSettle.getInsiteIncomeAmount());
            updateInfo.setTotalOutcomeAmount(workOrderSettle.getTotalOutcomeAmount());
            updateInfo.setRemark(workOrderSettle.getRemark());
            workOrderSettleMapper.updateByPrimaryKeySelective(updateInfo);
        }

    }

    /**
     * 结算确认
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public void confirm(String settleNo,String remark ,String staffCode, String staffName) {
        AssertUtils.hasText(settleNo, "结算单号为空");
        AssertUtils.hasText(staffCode, "结算确认人为空");

        List<WorkOrderSettleConfirm> confirms = workOrderSettleConfirmMapper.selectBySettleNo(settleNo);
        Optional<WorkOrderSettleConfirm> optional = confirms.stream().filter(c -> c.getStaffCode().equals(staffCode)).findAny();
        if(!optional.isPresent()){
            throw new CRMException("你没有权限确认此结算单");
        }

        WorkOrderSettleConfirm confirmInfo = new WorkOrderSettleConfirm();
        confirmInfo.setSettleNo(settleNo);
        confirmInfo.setStatus(WorkOrderSettleConfirmStatus.CONFIRMED);
        confirmInfo.setModifiedBy(staffName);
        confirmInfo.setStaffCode(staffCode);
        confirmInfo.setRemark(remark);

        workOrderSettleConfirmMapper.confirm(confirmInfo);

        if (remark != null){
            WorkOrderSettle settle = new WorkOrderSettle();
            settle.setSettleNo(settleNo);
            settle.setRemark(remark);
            workOrderSettleMapper.updateByPrimaryKeySelective(settle);
        }

        // 是否结算完成
        boolean settled = true;

        for (WorkOrderSettleConfirm confirm : confirms) {
            if(confirm.getStaffRole().equals(AmibaStaffRole.MANAGER)){
                if(!confirm.getStatus().equals(WorkOrderSettleConfirmStatus.CONFIRMED)){
                    settled = false;
                    break;
                }
            }
        }

        // 如果已结算完成, 更改工单状态为已结算
        if(settled){
            WorkOrderSettle workOrderSettle = workOrderSettleMapper.selectBySettleNo(settleNo);

            if(!workOrderSettle.getStatus().equals(WorkOrderSettleStatus.SETTLED)){
                // 结算单状态为已结算
                WorkOrderSettle updateSettle = new WorkOrderSettle();
                updateSettle.setSettleNo(workOrderSettle.getSettleNo());
                updateSettle.setStatus(WorkOrderSettleStatus.SETTLED);
                updateSettle.setSettledTime(new Date());
                workOrderSettleMapper.updateByPrimaryKeySelective(updateSettle);
            }

            // 工单状态已结算
            workOrderService.settled(workOrderSettle.getWorkOrderNo());
        }
    }

    @Override
    public WorkOrderSettleStaffs findSettleStaffsByWorkOrderNo(String workOrderNo) {
        WorkOrder workOrder = workOrderService.findByWorkOrderNo(workOrderNo);


        WorkOrderSettleStaffs result = new WorkOrderSettleStaffs();

        // 发起工单阿米巴成员列表
        List<AmibaStaff> fromAmibaStaffs = amibaStaffService.findByAmibaId(workOrder.getCreateAmibaId());

        // 付款方巴员
        AmibaStaff createStaff = new AmibaStaff();
        createStaff.setStaffCode(workOrder.getCreateStaffCode());
        createStaff.setStaffName(workOrder.getCreateStaffName());
        createStaff.setStaffMobile(workOrder.getCreateStaffMobile());
        result.setPayMember(createStaff);

        // 付款方巴长
        List<AmibaStaff> managers = fromAmibaStaffs.stream()
            .filter(s -> s.getRole() == AmibaStaffRole.MANAGER.getValue())
            .collect(Collectors.toList());
        // 付款方巴长没有设置, 则不能结算啊, 因为没有人确认
        if (CollectionUtils.isEmpty(managers)) {
            throw new CRMException("付款阿米巴没有设置巴长");
        }
        // 有多个巴长的话,没有办法,第一个巴长确定吧。
        AmibaStaff createStaffManager = managers.get(0);
        result.setPayManager(createStaffManager);

        List<AmibaStaff> receiveStaffs = amibaStaffService.findByAmibaId(workOrder.getReceiveAmibaId());

        // 收款方巴员信息, 不需要手机号,直接从工单上取吧,如果需要手机号,则需要查库了。
        AmibaStaff toStaff = new AmibaStaff();
        toStaff.setStaffCode(workOrder.getClaimStaffCode());
        toStaff.setStaffName(workOrder.getClaimStaffName());
        toStaff.setStaffMobile(workOrder.getClaimStaffMobile());
        result.setReceiveMember(toStaff);

        // 收款方巴长信息
        Optional<AmibaStaff> optional = receiveStaffs.stream()
            .filter(s -> s.getRole() == AmibaStaffRole.MANAGER.getValue())
            .findFirst();
        if(!optional.isPresent()){
            throw new CRMException("收款阿米巴没有设置巴长");
        }
        AmibaStaff toStaffManager = optional.get();
        result.setReceiveManager(toStaffManager);

        return result;
    }

    @Override
    public WorkOrderSettle findByWorkOrderNo(String workOrderNo) {
        WorkOrderSettle workOrderSettle = workOrderSettleMapper.selectDetailByWorkOrderNo(workOrderNo);

        if(Objects.nonNull(workOrderSettle)){
            List<WorkOrderSettleConfirm> confirms = workOrderSettleConfirmMapper.selectBySettleNo(workOrderSettle.getSettleNo());
            workOrderSettle.setConfirms(confirms);
        }

        return workOrderSettle;
    }

    @Override
    public PageInfo<WorkOrderSettleConfirmResult> findByPage(WorkOrderSettleQuery queryInfo) {

        PageHelper.startPage(queryInfo.getPage(), queryInfo.getPageSize());

        // 真是失败, 唉。
        if (StringUtils.isEmpty(queryInfo.getStaffCode()) && StringUtils.isNotEmpty(queryInfo.getStatus())) {
            if (queryInfo.getStatus().equals(WorkOrderSettleConfirmStatus.UN_CONFIRM.name())) {
                queryInfo.setStatus(WorkOrderSettleStatus.UN_SETTLE.name());
            } else if (queryInfo.getStatus().equals(WorkOrderSettleConfirmStatus.CONFIRMED.name())) {
                queryInfo.setStatus(WorkOrderSettleStatus.SETTLED.name());
            }
        }

        List<WorkOrderSettleConfirmResult> lstResult = StringUtils.isEmpty(queryInfo.getStaffCode())
            ? workOrderSettleMapper.selectByQueryWithoutStaffCode(queryInfo)
            : workOrderSettleMapper.selectByQuery(queryInfo);

        if(queryInfo.getIncludeConfirms()){
            List<String> settleNos = lstResult.stream()
                .map(WorkOrderSettleConfirmResult::getSettleNo)
                .distinct()
                .collect(Collectors.toList());
            List<WorkOrderSettleConfirm> confirms = workOrderSettleConfirmMapper.selectBySettleNos(settleNos);
            for (WorkOrderSettleConfirmResult workOrderSettleConfirmResult : lstResult) {
                List<WorkOrderSettleConfirm> settleConfirms = confirms.stream().filter(c -> c.getSettleNo().equals(workOrderSettleConfirmResult.getSettleNo()))
                    .collect(Collectors.toList());
                workOrderSettleConfirmResult.setConfirms(settleConfirms);
            }
        }

        return new PageInfo<>(lstResult);
    }

    @Override
    public WorkOrderSettle findBySettleNo(String settleNo) {
        if(StringUtils.isEmpty(settleNo)){
            return null;
        }
        WorkOrderSettle workOrderSettle = workOrderSettleMapper.selectBySettleNo(settleNo);
        return workOrderSettle;
    }

    private WorkOrderSettleConfirm buildSettleConfirm(String settleNo, String staffCode, String staffName,
                                                      AmibaStaffRole staffRole,
                                                      WorkOrderSettleConfirmSettleType settleType,
                                                      String createBy,int flag) {
        WorkOrderSettleConfirm settleConfirm = new WorkOrderSettleConfirm();
        settleConfirm.setSettleNo(settleNo);
        if(flag == 0) {
            settleConfirm.setStatus(WorkOrderSettleConfirmStatus.CONFIRMED);
        }else{
            settleConfirm.setStatus(WorkOrderSettleConfirmStatus.UN_CONFIRM);
        }
        settleConfirm.setSettleType(settleType);
        settleConfirm.setCreatedBy(createBy);
        settleConfirm.setModifiedBy(createBy);
        settleConfirm.setStaffCode(staffCode);
        settleConfirm.setStaffName(staffName);
        settleConfirm.setStaffRole(staffRole);
        return settleConfirm;
    }

    @Override
    public List<WorkOrderSettle> findByOrderNo(String orderNo) {
        AssertUtils.notNull(orderNo,"订单号为空！");
        return workOrderSettleMapper.selectByOrderNo(orderNo);
    }

    @Override
    public List<WorkOrderSettle> findByFromAmibaId(Integer id) {
        AssertUtils.notNull(id,"id为空!");
        return workOrderSettleMapper.selectByFromAmibaId(id);

    }

    @Override
    public List<WorkOrderSettle> findByToAmibaId(Integer id) {
        AssertUtils.notNull(id,"id为空!");
        return workOrderSettleMapper.selectByToAmibaId(id);
    }

    @Override
    public void updateCreditParty(WorkOrderSettle workOrderSettle) {
        AssertUtils.notNull(workOrderSettle,"参数为空！！");
        AssertUtils.notNull(workOrderSettle.getId(),"id为空！");
       //AssertUtils.notNull(workOrderSettle.getCreditParty(),"挂账责任方为空！");
        workOrderSettleMapper.updateByPrimaryKeySelective(workOrderSettle);
    }

    @Override
    public List<WorkOrderSettleConfirm> findConfirmsBySettleNo(String settleNo) {

        List<WorkOrderSettleConfirm> confirms = workOrderSettleConfirmMapper.selectBySettleNo(settleNo);
        return confirms;
    }

    @Override
    public List<WorkOrderSettleConfirm> findConfirmsBySettleNos(List<String> settleNos) {
        List<WorkOrderSettleConfirm> workOrderSettleConfirms = workOrderSettleConfirmMapper.selectBySettleNos(settleNos);
        return workOrderSettleConfirms;
    }

    @Override
    public List<WorkOrderSettle> findAll(WorkOrderSettleStatus status) {
        return workOrderSettleMapper.findAll(status);
    }

    @Override
    public List<WorkOrderSettle> findGradeByOrderNo(String orderNo) {
        AssertUtils.notNull(orderNo,"订单号为空！");
        return workOrderSettleMapper.selectGradeByOrderNo(orderNo);
    }

    @Override
    public int findUnGradeOrderCount(String salerCode) {
        return workOrderSettleMapper.selectUnGradeOrderCount(salerCode);
    }

    /**
     * 查询交付经理所受理的已评价订单数量
     * @param staffCode 交付经理编号
     * @return
     */
    @Override
    public Integer findMyEvaluatedOrderCount(String staffCode) {
        return workOrderSettleMapper.selectMyEvaluatedOrderCount(staffCode);
    }
}